home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / dtype / xpkdt10b.lha / Src / dispatch.c < prev   
C/C++ Source or Header  |  1995-11-21  |  11KB  |  340 lines

  1. /*
  2. **    dispatch.c - dispatcher for XPK DataType class
  3. **    Copyright © 1995 Michael Letowski
  4. */
  5.  
  6. #include <exec/types.h>
  7. #include <exec/memory.h>
  8. #include <dos/dos.h>
  9. #include <dos/dosasl.h>
  10. #include <intuition/classes.h>
  11. #include <datatypes/datatypesclass.h>
  12. #include <datatypes/datatypes.h>
  13. #include <libraries/xpk.h>
  14. #include <utility/tagitem.h>
  15. #include <support/types.h>
  16. #include <support/dos.h>
  17.  
  18. #include <string.h>
  19.  
  20. #include <proto/dos.h>
  21. #include <proto/exec.h>
  22. #include <proto/datatypes.h>
  23. #include <proto/intuition.h>
  24. #include <proto/utility.h>
  25. #include <clib/support_protos.h>
  26.  
  27. #include "classbase.h"
  28. #include "dispatch.h"
  29.  
  30.  
  31. /****** xpk.datatype/xpk.datatype *******************************************
  32. *
  33. *   NAME
  34. *       xpk.datatype -- data type for XPK and PowerPacker compressed files.
  35. *
  36. *   FUNCTION
  37. *       The xpk data type is used to decompress XPK and PowerPacker
  38. *       compressed files. Decompressed files are then placed in "T:" logical
  39. *       directory and passed again to DataTypes system via NewDTObject().
  40. *       DataTypes system is then free to handle them (it will usually show
  41. *       contents of a decompressed file).
  42. *
  43. *   METHODS
  44. *       OM_NEW -- Decompress source file, place it in "T:" directory and call
  45. *                 OM_NEW method on that file.
  46. *
  47. *       OM_DISPOSE -- Delete the object and all associated temporary files.
  48. *
  49. *   NOTES
  50. *       Since the data type just calls OM_NEW method on a decompressed file
  51. *       it will work for files which were compressed several times (eg. DLTA
  52. *       encoded and SHRI compressed).
  53. *
  54. *   BUGS
  55. *       Will not work for AmigaGuide® compressed files (due to a bug in
  56. *       amigaguide.datatype, I suspect).
  57. *       Can not handle encrypted files.
  58. *
  59. *   SEE ALSO
  60. *       amigaguide.datatype, xpkmaster.library, datatypes.library.
  61. *
  62. *****************************************************************************
  63. *
  64. */
  65.  
  66.  
  67. /*
  68. **    Private structures
  69. */
  70. struct XPKData
  71. {
  72.     Object *xd_Object;
  73.     STRPTR  xd_Name;
  74. };    /* XPKData */
  75.  
  76.  
  77. /*
  78. **    Private prototypes
  79. */
  80. STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg);
  81. STATIC Object *NewXPK(Class *cl, Object *o, Msg msg);
  82. STATIC Object *DisposeXPK(Class *cl, Object *o, Msg msg);
  83. STATIC Object *DefaultXPK(Class *cl, Object *o, Msg msg);
  84. STATIC STRPTR CreateTempFile(struct ClassBase *cb, STRPTR name);
  85. STATIC VOID DeleteTempFile(struct ClassBase *cb, STRPTR name);
  86. STATIC LONG XPK2DOS(struct ClassBase *cb, LONG xpkError);
  87.  
  88.  
  89. /*
  90. **    DataTypes stubs
  91. */
  92. STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
  93. STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
  94.  
  95.  
  96. /*
  97. **    xpk.h kludge
  98. */
  99. #pragma tagcall XpkBase XpkUnpackTags 30 801
  100.  
  101.  
  102. /*
  103. **    Public functions
  104. */
  105. Class *InitClass(struct ClassBase *cb)
  106. {
  107.     Class *CL;
  108.  
  109.     /* Create our class (an instance of XPKData) */
  110.     if(CL=MakeClass(DATATYPENAME,SUPERCLASSNAME,NULL,sizeof(struct XPKData),0))
  111.     {
  112.         CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
  113.         CL->cl_UserData=(ULONG)cb;
  114.         AddClass(CL);
  115.     }
  116.     return(CL);
  117. }    /* InitClass */
  118.  
  119.  
  120. /*
  121. **    Level 1 private functions
  122. */
  123. STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg)
  124. {
  125.     Object *Obj;
  126.  
  127.     switch(msg->MethodID)
  128.     {
  129.         case OM_NEW:            Obj=NewXPK(cl,o,msg);                break;
  130.         case OM_DISPOSE:    Obj=DisposeXPK(cl,o,msg);        break;
  131.         default:                    Obj=DefaultXPK(cl,o,msg);        break;
  132.     }
  133.     return(Obj);
  134. }    /* Dispatch */
  135.  
  136.  
  137. /*
  138. **    Level 2 private functions
  139. */
  140. STATIC Object *NewXPK(Class *cl, Object *o, Msg msg)
  141. {
  142.     STATIC CONST struct TagItem UnpackTags[]=
  143.     {
  144.         {XPK_PassThru,    TRUE},
  145.         {TAG_DONE,            0}
  146.     };    /* UnpackTags */
  147.     STATIC CONST Tag FilterTags[]=
  148.     {
  149.         DTA_SourceType,DTA_DataType,DTA_Name,DTA_Handle,TAG_DONE
  150.     };    /* FilterTags */
  151.  
  152.     struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
  153.     struct TagItem *Clone,*Tag;
  154.     struct TagItem *Attrs=((struct opSet *)msg)->ops_AttrList;
  155.     Object *NewObj=NULL;
  156.     struct XPKData *XD;
  157.     STRPTR Name,RealName;
  158.     BPTR Lock,Lock2,Handle;
  159.     LONG Err,RC=0;
  160.  
  161.     try(Clone=CloneTagItems(Attrs),    NO_CLONE);
  162.  
  163.     /* Get name and object lock */
  164.     RealName=    (STRPTR)GetTagData(DTA_Name,NULL,Clone);
  165.     Lock=            (BPTR)GetTagData(DTA_Handle,NULL,Clone);
  166.     try(RealName && Lock, NO_LOCK);
  167.  
  168.     /* Remove unnecessary attributes */
  169.     FilterTagItems(Clone,FilterTags,TAGFILTER_NOT);
  170.  
  171.     if(Name=CreateTempFile(cb,RealName))                    /* Create temporary file name */
  172.     {
  173.         Err=XPKERR_IOERRIN;                                                    /* No success yet */
  174.         if(Lock2=DupLock(Lock))                                            /* Get duplicate of lock */
  175.             if(Handle=OpenFromLock(Lock2))                        /* Open from that lock */
  176.             {                                                                                    /* Could open - Lock2 is invalid */
  177.                 /* Do unpacking */
  178.                 Err=XpkUnpackTags(XPK_InFH,            Handle,
  179.                                                     XPK_OutName,    Name,
  180.                                                     TAG_MORE,            UnpackTags);
  181.                 Close(Handle);                                                    /* Close file */
  182.             }
  183.             else                                                                            /* Could not open */
  184.                 UnLock(Lock2);                                                    /* Unlock file */
  185.             
  186.         if(Err==XPKERR_OK || Err==XPKERR_NOTPACKED)    /* Error? */
  187.             /* Create new object */
  188.             if(NewObj=(Object *)DoSuperMethodA(cl,o,msg))
  189.             {
  190.                 XD=INST_DATA(cl,NewObj);
  191.                 if(XD->xd_Object=NewDTObjectA(Name,Clone))
  192.                 {
  193.                     SetAttrs(NewObj,DTA_ObjName,RealName,TAG_DONE);
  194.                     XD->xd_Name=Name;
  195.                 }
  196.                 else                                                                        /* Could not create object */
  197.                 {
  198.                     RC=IoErr();                                                        /* Get DOS error code */
  199.                     CoerceMethod(cl,NewObj,OM_DISPOSE);        /* Destroy object (super class) */
  200.                     NewObj=NULL;                                                    /* Mark this fact */
  201.                 }
  202.             }
  203.             else                                                                            /* Error creating object */
  204.                 RC=IoErr();                                                            /* Get DOS error code */
  205.         else                                                                                /* Error unpacking */
  206.             RC=XPK2DOS(cb,Err);                                                /* Get DOS error code */
  207.     }
  208.     else                                                                                    /* Error creating temp file */
  209.         RC=IoErr();                                                                    /* Get DOS error code */
  210.  
  211.     unless(NewObj)                                                                /* New object not created */
  212.         DeleteTempFile(cb,Name);                                        /* Delete temporary file */
  213.      
  214.     /* Exceptions */
  215.     SetIoErr(RC);                                                                    /* Set error code */
  216.     catch(NO_LOCK,    );
  217.     catch(NO_CLONE,    FreeTagItems(Clone));
  218.     return(NewObj);
  219. }    /* NewXPK */
  220.  
  221. STATIC Object *DisposeXPK(Class *cl, Object *o, Msg msg)
  222. {
  223.     struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
  224.     struct XPKData *XD=INST_DATA(cl,o);
  225.  
  226.     if(XD->xd_Object)    DisposeDTObject(XD->xd_Object);
  227.     if(XD->xd_Name)        DeleteTempFile(cb,XD->xd_Name);
  228.     return((Object *)DoSuperMethodA(cl,o,msg));
  229. }    /* DisposeXPK */
  230.  
  231. STATIC Object *DefaultXPK(Class *cl, Object *o, Msg msg)
  232. {
  233.     struct XPKData *XD=INST_DATA(cl,o);
  234.  
  235.     return((Object *)DoMethodA(XD->xd_Object,msg));
  236. }    /* DefaultXPK */
  237.  
  238.  
  239. /*
  240. **    Level 3 private functions
  241. */
  242. STATIC STRPTR CreateTempFile(struct ClassBase *cb, STRPTR name)
  243. {
  244.     STRPTR Name,RealName=FilePart(name);
  245.     ULONG Len;
  246.     BPTR DirLock;
  247.  
  248.     Len=strlen(RealName)+24;
  249.     if(Name=AllocVec(Len,MEMF_PUBLIC))                        /* Allocate space for name */
  250.     {                                                                                            /* Space allocated */
  251.         SPrintf(Name,"T:XPKDT-%08lx-T%04ld",ThisProcessS,cb->cb_UniqueCnt++);
  252.         if(DirLock=CreateDir(Name))                                    /* Try to create directory */
  253.         {                                                                                        /* Could create directory */
  254.             AddPart(Name,RealName,Len);                                /* Append file name */
  255.             UnLock(DirLock);                                                    /* Free lock */
  256.         }
  257.         else                                                                                /* Dir not created */
  258.         {                                                                                        /* Create unique file name */
  259.             strcat(Name,"-");                                                    /* Append dash */
  260.             strcat(Name,RealName);                                        /* Append file name */
  261.         }
  262.     }
  263.     return(Name);
  264. }    /* CreateTempFile */
  265.  
  266. STATIC VOID DeleteTempFile(struct ClassBase *cb, STRPTR name)
  267. {
  268.     STRPTR Sep;
  269.  
  270.     if(name)                                                                            /* Name valid */
  271.     {
  272.         Sep=PathPart(name);                                                    /* Find path/file separator */
  273.         DeleteFile(name);                                                        /* Delete file */
  274.         if(Sep!=FilePart(name))                                            /* Dir component present */
  275.         {
  276.             *Sep='\0';                                                                /* Null terminate string */
  277.             DeleteFile(name);                                                    /* Delete directory */
  278.         }
  279.         FreeVec(name);                                                            /* Free space */
  280.     }
  281. }    /* DeleteTempFile */
  282.  
  283. STATIC LONG XPK2DOS(struct ClassBase *cb, LONG xpkErr)
  284. {
  285.     LONG DOSErr=ThisProcessS->pr_Result2;
  286.  
  287.     unless(DOSErr)                                                                /* Error not set */
  288.         switch(xpkErr)
  289.         {
  290.             case XPKERR_NOFUNC:                DOSErr=ERROR_NOT_IMPLEMENTED;                        break;
  291.             case XPKERR_NOFILES:            DOSErr=ERROR_NOT_IMPLEMENTED;                        break;
  292.             case XPKERR_IOERRIN:            DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  293.             case XPKERR_IOERROUT:            DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  294.             case XPKERR_CHECKSUM:            DOSErr=DTERROR_INVALID_DATA;                        break;
  295.             case XPKERR_VERSION:            DOSErr=ERROR_INVALID_RESIDENT_LIBRARY;    break;
  296.             case XPKERR_NOMEM:                DOSErr=ERROR_NO_FREE_STORE;                            break;
  297.             case XPKERR_LIBINUSE:            DOSErr=ERROR_INVALID_RESIDENT_LIBRARY;    break;
  298.             case XPKERR_WRONGFORM:        DOSErr=DTERROR_UNKNOWN_COMPRESSION;            break;
  299.             case XPKERR_SMALLBUF:            DOSErr=ERROR_BUFFER_OVERFLOW;                        break;
  300.             case XPKERR_LARGEBUF:            DOSErr=ERROR_BUFFER_OVERFLOW;                        break;
  301.             case XPKERR_WRONGMODE:        DOSErr=DTERROR_UNKNOWN_COMPRESSION;            break;
  302.             case XPKERR_NEEDPASSWD:        DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  303.             case XPKERR_CORRUPTPKD:        DOSErr=DTERROR_INVALID_DATA;                        break;
  304.             case XPKERR_MISSINGLIB:        DOSErr=ERROR_INVALID_RESIDENT_LIBRARY;    break;
  305.             case XPKERR_BADPARAMS:        DOSErr=ERROR_TOO_MANY_ARGS;                            break;
  306.             case XPKERR_EXPANSION:        DOSErr=ERROR_BUFFER_OVERFLOW;                        break;
  307.             case XPKERR_NOMETHOD:            DOSErr=ERROR_INVALID_RESIDENT_LIBRARY;    break;
  308.             case XPKERR_ABORTED:            DOSErr=ERROR_BREAK;                                            break;
  309.             case XPKERR_TRUNCATED:        DOSErr=DTERROR_NOT_ENOUGH_DATA;                    break;
  310.             case XPKERR_WRONGCPU:            DOSErr=ERROR_INVALID_RESIDENT_LIBRARY;    break;
  311.             case XPKERR_PACKED:                DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  312.             case XPKERR_NOTPACKED:        DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  313.             case XPKERR_FILEEXISTS:        DOSErr=ERROR_OBJECT_EXISTS;                            break;
  314.             case XPKERR_OLDMASTLIB:        DOSErr=ERROR_INVALID_RESIDENT_LIBRARY;    break;
  315.             case XPKERR_OLDSUBLIB:        DOSErr=ERROR_INVALID_RESIDENT_LIBRARY;    break;
  316.             case XPKERR_NOCRYPT:            DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  317.             case XPKERR_NOINFO:                DOSErr=ERROR_INVALID_RESIDENT_LIBRARY;    break;
  318.             case XPKERR_LOSSY:                DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  319.             case XPKERR_NOHARDWARE:        DOSErr=ERROR_NOT_IMPLEMENTED;                        break;
  320.             case XPKERR_BADHARDWARE:    DOSErr=ERROR_NOT_IMPLEMENTED;                        break;
  321.             case XPKERR_WRONGPW:            DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  322.             default:                                    DOSErr=ERROR_OBJECT_WRONG_TYPE;                    break;
  323.         }
  324.     return(DOSErr);
  325. }    /* XPK2DOS */
  326.  
  327.  
  328. /*
  329. **    DataTypes stubs
  330. */
  331. STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
  332. {
  333.     return(SetDTAttrsA(o,NULL,NULL,(struct TagItem *)&data));
  334. }    /* LocSetDTAttrs */
  335.  
  336. STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
  337. {
  338.     return(GetDTAttrsA(o,(struct TagItem *)&data));
  339. }    /* LocGetDTAttrs */
  340.